#include "Rtsp_Decod.h"
#include <chrono>

Rtsp_Decod::Rtsp_Decod(QObject *parent)
    : QObject(parent)
{
    avformat_network_init();
}

Rtsp_Decod::~Rtsp_Decod()
{
    close();
}


bool Rtsp_Decod::open(const std::string& url){

    AVDictionary* options = nullptr;
    av_dict_set(&options, "rtsp_transport", "tcp", 0); // 使用TCP传输

    // 打开输入流并查找流信息
    int ret = avformat_open_input(&formatContext, url.c_str(), nullptr, nullptr);
    if (ret < 0) {
        qDebug() << "Could not open source file:" << url.c_str();
        return false;
    }

    // 查找流信息
    ret = avformat_find_stream_info(formatContext, nullptr);
    if (ret < 0) {
        qDebug() << "Could not find stream information";
        return false;
    }

    // 打印流信息
    std::cout << "打印相关信息\n";
    av_dump_format(formatContext, 0, url.c_str(), 0);

    // 查找视频流
    videoStream = nullptr;
    for (unsigned int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = formatContext->streams[i];
            break;
        }
    }
    if (!videoStream) {
        qDebug() << "Could not find video stream";
        return false;
    }

    // 查找并打开解码器
    AVCodec *codec = avcodec_find_decoder(videoStream->codecpar->codec_id);
    if (!codec) {
        qDebug() << "Codec not found";
        return false;
    }
    //编解码
    codecContext = avcodec_alloc_context3(codec);
    if (!codecContext) {
        qDebug() << "Could not allocate video codec context";
        return false;
    }
    //将视频流的编解码器参数复制到刚分配的编解码器上下文中
    ret = avcodec_parameters_to_context(codecContext, videoStream->codecpar);
    if (ret < 0) {
        qDebug() << "Could not copy codec parameters to codec context";
        return false;
    }
    //打开编解码器
    ret = avcodec_open2(codecContext, codec, nullptr);
    if (ret < 0) {
        qDebug() << "Could not open codec";
        return false;
    }

    // 初始化图像转换上下文
    swsContext = sws_getContext(
        codecContext->width,    //原始帧图像宽度
        codecContext->height,   //原始帧图像高度
        codecContext->pix_fmt,  //原始帧图像格式
        show_width,        //处理后的图像宽度
        show_height,       //处理后的图像高度
        AV_PIX_FMT_RGB24,       //处理后的图像格式
        SWS_BILINEAR,
        nullptr,
        nullptr,
        nullptr
    );
    if (!swsContext) {
        // 处理错误：无法创建SwsContext
        qDebug() << "Could not allocate swsContext";
        return false;
    }else{
        
    }

    return true;
}
void Rtsp_Decod::close() {
    if (formatContext) {
        avformat_close_input(&formatContext);
    }
    if (codecContext) {
        avcodec_free_context(&codecContext);
    }
    if (swsContext) {
        sws_freeContext(swsContext);
    }
}
void Rtsp_Decod::decode(uint8_t* rgbFrame) {
    //准备好相关数据的内存
    AVPacket packet;
    av_init_packet(&packet);

    AVFrame* frame = av_frame_alloc();
    if (!frame) {
        qDebug() << "Could not allocate frame";
        return;
    }
    // 转换图像格式并发出信号(使用QImage来接收sws_scale函数的输出)
    QImage rgbFrame (show_width, show_height, QImage::Format_RGB888);
    uint8_t* rgbFrame_dst[] = { rgbFrame.bits() };//地址指定
    int dstStride[4];
    // AV_PIX_FMT_RGB24 对应于 QImage::Format_RGB888
    av_image_fill_linesizes(dstStride, AV_PIX_FMT_RGB24, show_width);

    while ((av_read_frame(formatContext, &packet) >= 0)) //解封转
    {
        if (packet.stream_index == videoStream->index) 
        {
            int ret = avcodec_send_packet(codecContext, &packet);
            if (ret < 0) {
                qDebug() << "Error sending a packet for decoding";
                // continue;
                break;
            }

            while (ret >= 0) 
            {
                ret = avcodec_receive_frame(codecContext, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                } else if (ret < 0) {
                    qDebug() << "Error during decoding";
                    goto cleanup;
                }
                // 确保frame->data不为NULL
                if (!frame->data) {
                    qDebug() << "Frame data is NULL";
                    goto cleanup;
                }

                auto zero = std::chrono::high_resolution_clock::now();
                // 进行格式转换和分辨率转换
                sws_scale(
                    swsContext,//转换的上下文
                    (const uint8_t * const *)frame->data,//输入图像数据的指针数组
                    frame->linesize,//输入图像每一行或每一列的步长数组
                    0,//// 输入图像的起始 y 坐标
                    frame->height,//输入图像的高
                    rgbFrame_dst,//指向输出图像数据的指针数组
                    dstStride//输出图像每一行或每一列的步长数组
                );

                // Q_EMIT newFrame(rgbFrame); // 发射信号
            }
        }
    }
    goto cleanup;

cleanup:
    av_frame_free(&frame);
    av_packet_unref(&packet);
}
// QImage Rtsp_Decod::AVFrameToQImage(AVFrame *frame, AVCodecContext *codecContext)
// {
//     // 确定图像的格式和尺寸
//     int width = codecContext->width;
//     int height = codecContext->height;
//     enum AVPixelFormat pixelFormat = codecContext->pix_fmt;
//     // 创建一个QImage实例，注意：这里假设像素格式为AV_PIX_FMT_RGB24
//     QImage image(width, height, QImage::Format_RGB888);
//     // 根据像素格式，可能需要不同的转换过程
//     if (pixelFormat == AV_PIX_FMT_YUV420P) {
//         // 对于YUV格式，需要转换为RGB格式
//         SwsContext* convertContext = sws_getContext(
//             width, height, (AVPixelFormat)pixelFormat,
//             width, height, AV_PIX_FMT_RGB24,
//             SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
//         if (!convertContext) {
//             // 转换上下文创建失败
//             return QImage();
//         }
//         // 分配内存以存储转换后的RGB帧
//         uint8_t *outBuffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1) * sizeof(uint8_t));
//         AVFrame *convertedFrame = av_frame_alloc();
//         av_image_fill_arrays(convertedFrame->data, convertedFrame->linesize, outBuffer, AV_PIX_FMT_RGB24, width, height, 1);
//         // 执行转换
//         sws_scale(convertContext, frame->data, frame->linesize, 0, height, convertedFrame->data, convertedFrame->linesize);
//         // 将转换后的数据复制到QImage中
//         for (int y = 0; y < height; y++) {
//             memcpy(image.scanLine(y), convertedFrame->data[0] + y * convertedFrame->linesize[0], width * 3);
//         }
//         // 释放资源
//         av_free(outBuffer);
//         av_frame_free(&convertedFrame);
//         sws_freeContext(convertContext);
//     } else if (pixelFormat == AV_PIX_FMT_RGB24) {
//         // 如果已经是RGB格式，直接复制数据
//         for (int y = 0; y < height; y++) {
//             memcpy(image.scanLine(y), frame->data[0] + y * frame->linesize[0], width * 3);
//         }
//     } else {
//         // 其他格式需要不同的处理
//         // ...
//     }
//     return image;
// }
QImage Rtsp_Decod::AVFrameToQImage(AVFrame *frame, AVCodecContext *codecContext) {
    if (!frame || !codecContext) {
        return QImage(); // 返回空的 QImage
    }

    int width = codecContext->width;
    int height = codecContext->height;
    enum AVPixelFormat pixelFormat = codecContext->pix_fmt;

    QImage image;
    if (pixelFormat == AV_PIX_FMT_YUV420P) {
        SwsContext* convertContext = sws_getContext(
            width, height, (AVPixelFormat)pixelFormat,
            width, height, AV_PIX_FMT_RGB24,
            SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);

        if (!convertContext) {
            return QImage(); // 转换上下文创建失败
        }

        uint8_t *outBuffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1) * sizeof(uint8_t));
        if (!outBuffer) {
            sws_freeContext(convertContext);
            return QImage(); // 内存分配失败
        }

        AVFrame *convertedFrame = av_frame_alloc();
        if (!convertedFrame) {
            av_free(outBuffer);
            sws_freeContext(convertContext);
            return QImage(); // 内存分配失败
        }

        av_image_fill_arrays(convertedFrame->data, convertedFrame->linesize, outBuffer, AV_PIX_FMT_RGB24, width, height, 1);

        sws_scale(convertContext, frame->data, frame->linesize, 0, height, convertedFrame->data, convertedFrame->linesize);

        image = QImage(convertedFrame->data[0], width, height, convertedFrame->linesize[0], QImage::Format_RGB888);

        av_free(outBuffer);
        av_frame_free(&convertedFrame);
        sws_freeContext(convertContext);
    } else if (pixelFormat == AV_PIX_FMT_RGB24) {
        image = QImage(frame->data[0], width, height, frame->linesize[0], QImage::Format_RGB888);
    } else {
        // 其他格式需要不同的处理，这里可以添加更多的条件分支
        // ...
    }

    return image;
}
QImage Rtsp_Decod::frameToImage(AVFrame *frame) 
{ 
    QImage image; 

    // 获取图像的宽度和高度 
    int width = frame->width; 
    int height = frame->height; 

    // 创建 QImage 对象 
    image = QImage(width, height, QImage::Format_RGB888); 

    // 将 AVFrame 转换为 QImage 
    for (int y = 0; y < height; y++) { 
        for (int x = 0; x < width; x++) { 
            int index = y * frame->linesize[0] + x * 3; 
            int r = frame->data[0][index]; 
            int g = frame->data[0][index + 1]; 
            int b = frame->data[0][index + 2]; 
            image.setPixel(x, y, qRgb(r, g, b)); 
        } 
    } 
    return image; 
} 

void Rtsp_Decod::start()
{
    while (!isStopped()) {
        decode();
    }
}
void Rtsp_Decod::stop()
{
    // 设置一个标志，表示解码循环应该停止
    stopDecoding = true;
}
bool Rtsp_Decod::isStopped() const
{
    return stopDecoding;
}
void Rtsp_Decod::set_show_height(int a)
{
    show_height=a;
}
void Rtsp_Decod::set_show_width(int a)
{
    show_width=a;
}

bool Rtsp_Decod::isSuspendDecod() const{
    return suspendDecoding;
}
void Rtsp_Decod::set_SuspendDecod(bool a){
    suspendDecoding = a;
}

